package pl.rgolcz.antnet.testcases;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;

import pl.rgolcz.antnet.AntNet;
import pl.rgolcz.antnet.DijkstraShortestPath;
import pl.rgolcz.antnet.GraphReader;
import pl.rgolcz.antnet.IWeightedEdge;
import pl.rgolcz.antnet.Main;
import edu.uci.ics.jung.graph.Graph;

public class OptimalPercent
{
    private static final int N_RUN = 100;
    static double vapour = 0.1;
    static double alpha = 1.0;
    static double beta = 1.0;
    static double Q = 1.0;
    
    static List<Double> divergentList = new ArrayList<>();
    static List<Double> optimalList = new ArrayList<>();
    static List<Double> averageLengthList = new ArrayList<>();
    static List<Double> averageIterList = new ArrayList<>();
    
    
    static int root[] = {5, 24, 1, 20, 3, 8};
    static int dest[] = {21, 17, 14, 8, 4, 11};
    static double[] testValues = new double[] {0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0};
    
    
    public static void main(String[] s) throws IOException
    {
        for(double tmp : testValues)
        {
            beta = tmp;
            
            for(int i = 0; i < root.length; i++)
            {
                run(root[i], dest[i]);
            }
        }
        
        /* print results */
        System.out.println("# divergence");
        printResults(divergentList);
        
        System.out.println("# optimal");
        printResults(optimalList);
        
        System.out.println("# avglength");
        printResults(averageLengthList);
        
        System.out.println("# avgiter");
        printResults(averageIterList);
    }
    
    public static void printResults(List<Double> results)
    {
        System.out.print("      ");
        for(int j = 0; j < root.length; j++)
        {
            System.out.print(String.format("[%2d-%-2d] ", root[j], dest[j]));
        }
        System.out.println();
        
        int k = 0;
        for(int i = 0; i < testValues.length; i++)
        {
            System.out.print(String.format("%5.2f ", testValues[i]).replace(',', '.'));
            for(int j = 0; j < root.length; j++)
            {
                if(results.get(k) != null)
                {
                    System.out.print(String.format("%5.2f   ", results.get(k)).replace(',', '.'));
                }
                else
                {
                    System.out.print("   -    ");
                }
                k++;
            }
            System.out.println();
        }
    }
    
    public static void run(int root, int dest) throws IOException
    {
        /*System.out.println("Root vertex: " + root);
        System.out.println("Dest vertex: " + dest);*/

        Graph<Integer, IWeightedEdge> graph = null;

        /* Load the graph definition from file */
        try
        {
            graph = getGraph();
        }
        catch (IOException e)
        {
            System.out.println("Failed to load the graph");
            e.printStackTrace();
            System.exit(1);
        }

        /* Run Dijkstra algorithm */
        //System.out.println("\n-- Running Dijkstra algorithm --");
        DijkstraShortestPath<Integer> dijkstra = new DijkstraShortestPath<>(graph, root);
        dijkstra.run();
        List<Integer> dijkstraShortestPath = dijkstra.getShortestPath(dest);
        //System.out.println("Dijkstra shortest path: " + dijkstraShortestPath);
        //System.out.println("Dijkstra shortest path length: " + dijkstra.getShortestPathLength(dest));
        
        double optimalSolution = dijkstra.getShortestPathLength(dest);

        /* Run ant algorithm */
        int optimal = 0;
        int nonoptimal = 0;
        int divergent = 0;
        double avg = 0.0;
        int avgIter = 0;
        for(int i = 0; i < N_RUN; i++)
        {
            AntNet antnet = new AntNet(graph, root, dest);
            
            antnet.setAlpha(alpha);
            antnet.setBeta(beta);
            antnet.setQ(Q);
            antnet.setVapour(vapour);
            
            antnet.run();
            if(antnet.getSolutionLength() != null)
            {
                divergent++;
                avg += antnet.getSolutionLength();
                if(optimalSolution == antnet.getSolutionLength())
                {
                    optimal++;
                    
                    int iter = 0;
                    for(Double val : antnet.getSolutionLengthList())
                    {
                        if(val != null && val == optimalSolution)
                        {
                            break;
                        }
                        iter++;
                    }
                    avgIter += iter;
                }
                else
                {
                    nonoptimal++;
                }
            }
        }
        
        divergentList.add(divergent / (double) N_RUN);
        optimalList.add(optimal / (double) N_RUN);
        if(divergent != 0)
        {
            averageIterList.add(avgIter/ (double) divergent);
            averageLengthList.add(avg/(double) divergent);
        }
        else
        {
            averageIterList.add(null);
            averageLengthList.add(null);
        }
        
        /*System.out.println("Divergent:      " + divergent);
        System.out.println("Optimal:        " + optimal);
        if(divergent != 0.0)
        {
            System.out.println("Average length: " + avg/divergent);
            System.out.println("Average iter:   " + avgIter/divergent);            
        }
        else
        {
            System.out.println("Average length: -");
            System.out.println("Average iter:   -");
        }*/
    }
    
    /**
     * @return the graph for this demo
     * @throws IOException 
     */
    static Graph<Integer, IWeightedEdge> getGraph() throws IOException {

        //BufferedReader reader = new BufferedReader(new FileReader(new File("graph.net")));
        BufferedReader reader = new BufferedReader(new FileReader(new File("random.net")));
        
        GraphReader graphReader = new GraphReader(reader);
        Graph<Integer, IWeightedEdge> graph = graphReader.read();
        return graph;
    }
}
